//
//  AUNetworkManager.swift
//  rrrr
//
//  Created by A on 2025/9/20.
//

import Foundation
import Moya
import HandyJSON
import Alamofire

class NetworkManager {
    static let shared = NetworkManager()
    private init() {}

    private let provider = MoyaProvider<MultiTarget>()

    @discardableResult
    func request<T: HandyJSON>(_ URLString: String,
                               parameters: [String: Any]? = nil,
                               model: T.Type,
                               isJSON: Bool = true,
                               headers: [String: String]? = nil,
                               success: @escaping (_ result: (data: Any?, code: Int)) -> Void,
                               failure: @escaping (String?) -> Void) -> Cancellable? {

        let target = GenericTarget(url: URLString, method: .get, parameters: parameters, isJSON: isJSON, headers: headers)

        return provider.request(MultiTarget(target)) { result in
            switch result {
            case .success(let response):
                // 处理非 200 状态码
                guard response.statusCode == 200 else {
                    if let jsonObj = try? JSONSerialization.jsonObject(with: response.data, options: []),
                       let jsonDict = jsonObj as? [String: Any],
                       let msg = jsonDict["msg"] {
                        failure(String(describing: msg))
                    } else if let str = String(data: response.data, encoding: .utf8) {
                        print("Response body: \(str)")
                        failure( str)
                    } else {
                        failure( "服务器错误")
                    }
                    return
                }
                
                do {
                    
                    let jsonObj = try JSONSerialization.jsonObject(with: response.data, options: [])
                    
                    if let jsonDict = jsonObj as? [String: Any] {
                        if let auResult = AUResult.deserialize(from: jsonDict) {
                            if let code = auResult.code, code != 0 {
                                success((nil,code))
                            } else {
                                if let dict = auResult.data as? [String: Any] {
                                    let modelObj = T.deserialize(from: dict)
//                                    success((modelObj,auResult.code) as! (data: Any?, code: Int))
                                    success((modelObj, auResult.code ?? 0))
                                } else if let arr = auResult.data as? [[String: Any]] {
                                    let modelArr = [T].deserialize(from: arr)
//                                    success(modelArr)
                                    success((modelArr, auResult.code ?? 0))
                                } else {
//                                    success(nil)
                                    success((nil, auResult.code ?? 0))

                                }
                            }
                        } else {
//                            success(nil)
                            success((nil,  0))

                        }
                    }
                } catch {
                    print("JSON 解析错误: \(error)")
                    success((nil,  0))
                }

            case .failure(let error):
                let statusCode = error.response?.statusCode ?? -1
                failure( error.errorDescription)
            }
        }
    }

    @discardableResult
    func requestPOST<T: HandyJSON>(_ URLString: String,
                                   parameters: [String: Any]? = nil,
                                   model: T.Type,
                                   isJSON: Bool = true,
                                   headers: [String: String]? = nil,
                                   success: @escaping (_ result: (data: Any?, code: Int)) -> Void,
                                   failure: @escaping (String?) -> Void) -> Cancellable? {

        let target = GenericTarget(url: URLString, method: .post, parameters: parameters, isJSON: isJSON, headers: headers)

        return provider.request(MultiTarget(target)) { result in
            switch result {
            case .success(let response):
                print("Status Code: \(response.statusCode), Data Length: \(response.data.count)")
                // 处理非 200 状态码
                guard response.statusCode == 200 else {
                    if let jsonObj = try? JSONSerialization.jsonObject(with: response.data, options: []),
                       let jsonDict = jsonObj as? [String: Any],
                       let msg = jsonDict["msg"] {
                        failure(String(describing: msg))
                    } else if let str = String(data: response.data, encoding: .utf8) {
                        print("Response body: \(str)")
                        failure( str)
                    } else {
                        failure("服务错误")
                    }
                    return
                }

                do {
                    let jsonObj = try JSONSerialization.jsonObject(with: response.data, options: [])
                    
                    if let jsonDict = jsonObj as? [String: Any] {
                        if let auResult = AUResult.deserialize(from: jsonDict) {
                            if let code = auResult.code, code != 0 {
                                success((nil, code))
                            } else {
                                if let dict = auResult.data as? [String: Any] {
                                    let modelObj = T.deserialize(from: dict)
//                                    success((modelObj,auResult.code) as! (data: Any?, code: Int))
                                    success((modelObj, auResult.code ?? 0))
                                } else if let arr = auResult.data as? [[String: Any]] {
                                    let modelArr = [T].deserialize(from: arr)
//                                    success(modelArr)
                                    success((modelArr, auResult.code ?? 0))
                                } else {
//                                    success(nil)
                                    success((nil, auResult.code ?? 0))

                                }
                            }
                        } else {
//                            success(nil)
                            success((nil,  0))

                        }
                    }
                } catch {
                    print("JSON 解析错误: \(error)")
                    success((nil,  0))
                }

            case .failure(let error):
                let statusCode = error.response?.statusCode ?? -1
                failure( error.errorDescription)
            }
        }
    }
}

private struct GenericTarget: TargetType {
    static let baseURLString = "http://180.184.140.234:9999/"

    let url: String
    let method: Moya.Method
    let parameters: [String: Any]?
    let isJSON: Bool
    let headersDict: [String: String]?

    init(url: String, method: Moya.Method, parameters: [String: Any]?, isJSON: Bool, headers: [String: String]?) {
        self.url = url
        self.method = method
        self.parameters = parameters
        self.isJSON = isJSON
        self.headersDict = headers
    }

    var baseURL: URL {
        guard let url = URL(string: GenericTarget.baseURLString) else {
            fatalError("Invalid baseURLString")
        }
        return url
    }

    var path: String {
        if let url = URL(string: url) {
            return url.path + (url.query.map { "?\($0)" } ?? "")
        }
        return ""
    }

    var sampleData: Data { Data() }

    var task: Task {
        if method == .get {
            return .requestParameters(parameters: parameters ?? [:], encoding: URLEncoding.default)
        } else {
            if isJSON {
                return .requestParameters(parameters: parameters ?? [:], encoding: JSONEncoding.default)
            } else {
                return .requestParameters(parameters: parameters ?? [:], encoding: URLEncoding.httpBody)
            }
        }
    }

    var headers: [String : String]? { headersDict }
}
